package com.sherlocky.oss.qiniu.util;

import java.io.File;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import com.sherlocky.oss.qiniu.bean.MyRet;
import com.sherlocky.oss.qiniu.constants.QiniuOSSConstants;
import com.sherlocky.util.PropertiesUtil;

public class QiniuOSSUtil {
	private static final Log log = LogFactory.getLog(QiniuOSSUtil.class);
	private static final String ACCESS_KEY = PropertiesUtil.getValue(QiniuOSSConstants.PROPERTIES, QiniuOSSConstants.ACCESS_KEY);
	private static final String SECRET_KEY = PropertiesUtil.getValue(QiniuOSSConstants.PROPERTIES, QiniuOSSConstants.SECRET_KEY);
	private static final String PIPELINE = PropertiesUtil.getValue(QiniuOSSConstants.PROPERTIES, QiniuOSSConstants.PIPELINE);
	private static Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
	
	// 简单上传，使用默认策略
	public static String getUpToken(String bucket) {
	    return auth.uploadToken(bucket);
	}
	
	// 设置预处理、去除非限定的策略字段
	public static String getUpToken(String bucket, String fops, String notifyUrl, String persistentPipeline) {
	    return auth.uploadToken(bucket, null, 3600, new StringMap()
        .putNotEmpty("persistentOps", fops).putNotEmpty("persistentNotifyUrl", notifyUrl)
        .putNotEmpty("persistentPipeline", persistentPipeline)
        .put("returnBody", "{\"key\":$(fname),\"fsize\":$(fsize),\"width\":$(imageInfo.width),\"height\":$(imageInfo.height),\"hash\":$(etag),\"persistentId\":$(persistentId)}"), true);
	}
	
	/**
	 * 生成上传token
	 *
	 * @param bucket  空间名
	 * @param key     key，可为 null
	 * @param expires 有效时长，单位秒。默认3600s
	 * @param policy  上传策略的其它参数，如 new StringMap().put("endUser", "uid").putNotEmpty("returnBody", "")。
	 *        scope通过 bucket、key间接设置，deadline 通过 expires 间接设置
	 * @param strict  是否去除非限定的策略字段，默认true
	 * @return 生成的上传token
	 */
	public static String getUpToken(String bucket, String key, long expires, StringMap policy, boolean strict) {
		return auth.uploadToken(bucket, null, 3600, new StringMap()
		.put("callbackUrl", "call back url").putNotEmpty("callbackHost", "")
		.put("callbackBody", "key=$(key)&hash=$(etag)"));
	}
	
	// 覆盖上传
	public static String getUpToken1(String bucket) {
	    return auth.uploadToken(bucket, "key");
	}

	/*
	public static boolean delete(String bucketName, String key) {
		RSClient client = new RSClient(getMac());
		CallRet ret = client.delete(bucketName, key);
		return ret.ok();
	}
	
	public static Mac getMac() {
		return new Mac(ACCESS_KEY, SECRET_KEY);
	}
	
	public static String getUpToken(String bucketName) throws AuthException, JSONException {
		Mac mac = getMac();
		PutPolicy putPolicy = new PutPolicy(bucketName);
		return putPolicy.token(mac);
	}
	
	public static String getUpToken(String bucketName, String fops, String notifyUrl) throws AuthException, JSONException {
		Mac mac = getMac();
		PutPolicy putPolicy = new PutPolicy(bucketName);
		putPolicy.persistentOps = fops;
		putPolicy.persistentNotifyUrl = notifyUrl;
		putPolicy.persistentPipeline = "siyeccJobChannel1";
		return putPolicy.token(mac);
	}
	
	public static Entry getFileInfo(String bucketName, String key) {
		RSClient client = new RSClient(getMac());
		return client.stat(bucketName, key);
	}
	
	public static PutRet upload(String bucketName, String key, String filepath) throws AuthException, JSONException, FileNotFoundException {
		return upload(bucketName, key, new FileInputStream(new File(filepath)));
	}
	
	public static PutRet upload(String bucketName, String key, InputStream in) throws AuthException, JSONException {
		PutExtra extra = new PutExtra();
		return IoApi.Put(getUpToken(bucketName), key, in, extra);
	}
	*/
	
	public static MyRet upload(String bucketName, String key, File file, String fops, String notifyUrl) {
		String token = getUpToken(bucketName, fops, notifyUrl, PIPELINE);
		log.info("token : " + token);
		log.info("key : " + key);
		log.info("fops : " + fops);
		log.info("notifyUrl : " + notifyUrl);
		// 重用 uploadManager。一般地，只需要创建一个 uploadManager 对象
		UploadManager uploadManager = new UploadManager();
	    try {
	        Response res = uploadManager.put(file, key, token);//, getParams(), getMime(), false);
	         log.info(res);
	         log.info(res.bodyString());
	         // Map<String, Object> m = res.jsonToObject(HashMap.class);
	         MyRet ret = res.jsonToObject(MyRet.class);
	         ret.setResponse(res);
	         if (res.isOK()) {
	             //success
	        	 return ret;
	         } else {
	        	 log.error("上传失败！" + res.toString());
	        	 return ret;
	         }
	    } catch (QiniuException e) {
	        Response r = e.response;
	        // 请求失败时简单状态信息
	        log.error(r.toString());
	        try {
	            // 响应的文本信息
	            log.error(r.bodyString());
	        } catch (QiniuException e1) {
	            //ignore
	        }
	    }
	    return null;
	}
	
	// 七牛公开的的 hash 算法
	public static String urlsafeEncode(String str) {
		return UrlSafeBase64.encodeToString(str);
	}
	
	public static void main(String[] args) {
		System.out.println(urlsafeEncode("sherlocky:test.avi"));
	}
}

